package com.lzp.service.impl;

import com.lzp.mapper.OrderItemsMapper;
import com.lzp.mapper.OrderStatusMapper;
import com.lzp.mapper.OrdersMapper;
import com.lzp.pojo.*;
import com.lzp.pojo.bo.ShopcartBO;
import com.lzp.pojo.bo.SubmitOrderBO;
import com.lzp.pojo.vo.MerchantOrdersVO;
import com.lzp.pojo.vo.OrderVO;
import com.lzp.service.AddressService;
import com.lzp.service.ItemService;
import com.lzp.service.OrderService;
import com.lzp.utils.DateUtil;
import com.lzp.utils.enums.OrderStatusEnum;
import com.lzp.utils.enums.Yes0rNo;
import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 订单业务实现类
 *
 * @author dtyy
 * @date 2020/9/16
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private Sid sid;

    @Autowired
    private AddressService addressService;

    @Autowired
    private ItemService itemService;

    @Autowired
    private OrderItemsMapper orderItemsMapper;

    @Autowired
    private OrdersMapper ordersMapper;

    @Autowired
    private OrderStatusMapper orderStatusMapper;

    /**
     * 创建订单业务处理
     *
     * @param submitOrderBO  用户提交的订单数据
     * @param shopcartBOList
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public OrderVO createOrder(SubmitOrderBO submitOrderBO, List<ShopcartBO> shopcartBOList) {
        // 1 获取数据
        String userId = submitOrderBO.getUserId();
        String addressId = submitOrderBO.getAddressId();
        String itemSpecIds = submitOrderBO.getItemSpecIds();
        Integer payMethod = submitOrderBO.getPayMethod();
        String leftMsg = submitOrderBO.getLeftMsg();
        // 默认包邮，费用为0
        Integer postAmount = 0;

        // 2 保存新订单数据
        Orders newOrder = new Orders();
        // 2.1 生成订单id
        String orderId = sid.nextShort();
        newOrder.setId(orderId);
        newOrder.setUserId(userId);
        // 2.2 收货地址快照处理
        UserAddress address = addressService.queryUserAddress(userId, addressId);
        newOrder.setReceiverName(address.getReceiver());
        newOrder.setReceiverMobile(address.getMobile());
        newOrder.setReceiverAddress(address.getProvince() + " "
                + address.getCity() + " "
                + address.getDistrict() + " "
                + address.getDetail());
        // 2.3 其他数据
        newOrder.setPayMethod(payMethod);
        newOrder.setPostAmount(postAmount);
        newOrder.setLeftMsg(leftMsg);
        newOrder.setIsComment(Yes0rNo.NO.getCode());
        newOrder.setIsDelete(Yes0rNo.NO.getCode());
        newOrder.setCreatedTime(new Date());
        newOrder.setUpdatedTime(new Date());

        // 3 循环商品规格id，保存订单商品数据
        Integer totalAmount = 0;
        Integer realPayAmount = 0;
        String[] itemSpecIdArr = itemSpecIds.split(",");
        List<ShopcartBO> toBeRemovedShopcartList = new ArrayList<>();
        for (String itemSpecId : itemSpecIdArr) {
            // 3.1 获取规格的具体信息
            ItemsSpec itemsSpec = itemService.queryItemSpecBySpecId(itemSpecId);

            // 从redis中获取商品购买数量
            ShopcartBO shopcartBO = getBuyCountsFromShopcart(shopcartBOList, itemSpecId);
            int buyCounts = shopcartBO.getBuyCounts();
            toBeRemovedShopcartList.add(shopcartBO);

            // 计算价格
            totalAmount += itemsSpec.getPriceNormal() * buyCounts;
            realPayAmount += itemsSpec.getPriceDiscount() * buyCounts;

            // 获取商品、商品主图
            String itemId = itemsSpec.getItemId();
            Items item = itemService.getItemById(itemId);
            String itemImg = itemService.queryItemMainImgByItemId(itemId);

            // 封装数据
            OrderItems orderItem = new OrderItems();
            String subOrderId = sid.nextShort();
            orderItem.setId(subOrderId);
            orderItem.setOrderId(orderId);
            orderItem.setItemSpecId(itemSpecId);
            orderItem.setItemSpecName(itemsSpec.getName());
            orderItem.setPrice(itemsSpec.getPriceDiscount());
            orderItem.setBuyCounts(buyCounts);
            orderItem.setItemId(itemId);
            orderItem.setItemName(item.getItemName());
            orderItem.setItemImg(itemImg);
            // 入库
            orderItemsMapper.insert(orderItem);

            // 扣除库存
            itemService.decreaseItemSpecStock(itemSpecId, buyCounts);
        }

        // 2.4 设置总价格与实际支付价格
        newOrder.setTotalAmount(totalAmount);
        newOrder.setRealPayAmount(realPayAmount);
        // 2.5 订单数据入库
        ordersMapper.insert(newOrder);

        // 4 保存订单状态数据
        OrderStatus waitPayOrderStatus = new OrderStatus();
        waitPayOrderStatus.setOrderId(orderId);
        waitPayOrderStatus.setOrderStatus(OrderStatusEnum.WAIT_PAY.getCode());
        waitPayOrderStatus.setCreatedTime(new Date());
        orderStatusMapper.insert(waitPayOrderStatus);

        // 5 构建商户订单，用于传给支付中心记录流水
        // 支付中心参数BO，业务平台输出VO
        MerchantOrdersVO merchantOrdersVO = new MerchantOrdersVO();
        merchantOrdersVO.setMerchantOrderId(orderId);
        merchantOrdersVO.setMerchantUserId(userId);
        merchantOrdersVO.setAmount(realPayAmount + postAmount); // 实际支付金额 = 实际商品金额 + 运费
        merchantOrdersVO.setPayMethod(payMethod);

        // 6. 构建自定义订单VO
        OrderVO orderVO = new OrderVO();
        orderVO.setMerchantOrdersVO(merchantOrdersVO);
        orderVO.setOrderId(orderId);
        orderVO.setToBeRemovedShopcatdList(toBeRemovedShopcartList);

        return orderVO;
    }

    /**
     * 从Redis缓存中获取购买数量
     *
     * @param shopcartBOList 缓存中的购物车数据
     * @param itemSpecId     商品规格
     */
    private ShopcartBO getBuyCountsFromShopcart(List<ShopcartBO> shopcartBOList, String itemSpecId) {
        for (ShopcartBO shopcartBO : shopcartBOList) {
            if (itemSpecId.equals(shopcartBO.getSpecId())) {
                return shopcartBO;
            }
        }
        return null;
    }

    /**
     * 用户支付成功，更新平台订单状态
     *
     * @param merchantOrderId 订单id
     * @param orderStatus     订单状态码
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void updateOrderStatus(String merchantOrderId, Integer orderStatus) {
        OrderStatus paidStatus = new OrderStatus();
        paidStatus.setOrderId(merchantOrderId);
        paidStatus.setOrderStatus(orderStatus);
        paidStatus.setPayTime(new Date());

        orderStatusMapper.updateByPrimaryKeySelective(paidStatus);
    }

    /**
     * 查询订单状态
     *
     * @param orderId 订单id
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public OrderStatus queryOrderStatus(String orderId) {
        return orderStatusMapper.selectByPrimaryKey(orderId);
    }

    /**
     * 定时关闭超时订单
     * <p>
     * 对于刚关闭订单，用户就支付成功了，可以通过分布式锁解决。
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void closeOrder() {
        OrderStatus orderStatus = new OrderStatus();
        orderStatus.setOrderStatus(OrderStatusEnum.WAIT_PAY.getCode());
        List<OrderStatus> waitPayOrderList = orderStatusMapper.select(orderStatus);
        for (OrderStatus os : waitPayOrderList) {
            // 获取订单创建时间
            Date createdTime = os.getCreatedTime();
            // 与当前时间作比较
            int days = DateUtil.daysBetween(createdTime, new Date());
            if (days > 1) {
                // 超过一天，关闭订单
                doCloseOrder(os.getOrderId());
            }
        }
    }

    /**
     * 删除某一笔订单操作
     * <p>
     * TODO 后续会有分布式事务和分布式锁，或者结合延迟队列实现
     *
     * @param orderId 订单id
     */
    private void doCloseOrder(String orderId) {
        OrderStatus closeStatus = new OrderStatus();
        closeStatus.setOrderId(orderId);
        closeStatus.setOrderStatus(OrderStatusEnum.CLOSE.getCode());
        closeStatus.setCloseTime(new Date());
        orderStatusMapper.updateByPrimaryKeySelective(closeStatus);
    }

}
